package ochttp

import (
	"crypto/tls"
	"math/rand"
	"net"
	"net/http"
	"net/url"
	"time"
)

// 请求参数
type Request struct {
	// 方法
	Method string
	// body
	Data map[string]interface{}
	// 头部
	Header map[string]string
	// 请求路径
	Url string
	// 是否开启重试(默认3次)
	IsRetry bool
	// 重试次数
	RetryTimes int
}

// 请求客户端
type Client struct {
	// 超时时间(ms)
	Duration int
	// 代理
	Proxy []string
	// 基础路径
	BaseUrl string
	// 请求签的钩子
	OnBeforeRequest OnBeforeRequestHook
}

// 请求签的钩子函数
type OnBeforeRequestHook func(r *Request) error

// 发送GET请求
func (c *Client) Get(r *Request, target any) error {
	client := &http.Client{}
	if err := c.initRequest(r, client); err != nil {
		return err
	}
	req, err := http.NewRequest(r.Method, c.getPath(r), nil)
	if err != nil {
		return err
	}
	for k, v := range r.Header {
		req.Header.Set(k, v)
	}

	return nil
}

// 获取总请求路径
func (c *Client) getPath(r *Request) string {
	return c.BaseUrl + r.Url
}

// 请求的初始化
func (c *Client) initRequest(r *Request, server *http.Client) error {
	tr := &http.Transport{}
	// 先判断是否使用了代理
	if len(c.Proxy) != 0 {
		tr.Proxy = randomProxy(c.Proxy)
		tr.DialContext = (&net.Dialer{Timeout: 30 * time.Second, KeepAlive: 30 * time.Second}).DialContext
		tr.TLSClientConfig = &tls.Config{
			InsecureSkipVerify: true,
		}
	}
	server.Transport = tr
	server.Timeout = time.Duration(c.Duration)
	if err := c.OnBeforeRequest(r); err != nil {
		return err
	}
	return nil
}

// 设置随机代理
func randomProxy(proxyList []string) func(*http.Request) (*url.URL, error) {
	return func(*http.Request) (*url.URL, error) {
		proxyURL, err := url.Parse(proxyList[rand.Intn(len(proxyList))])
		if err != nil {
			return nil, err
		}
		return proxyURL, nil
	}
}
